package com.mida.app.report.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mida.app.report.enumData.DetailCode;
import com.mida.app.report.enumData.ReportProcessStatus;
import com.mida.app.report.enumData.ReportType;
import com.mida.app.report.innerdto.ReportFlowInfo;
import com.mida.app.report.process.impl.BaseProcess;
import com.mida.app.report.service.CacheService;
import com.mida.app.report.service.DetailCodingSystemService;
import com.mida.app.report.service.DocReportListNewService;
import com.mida.app.report.vo.*;
import com.mida.bms.report.api.DocReportServiceApi;
import com.mida.bms.report.vo.DocReportRequisitionRelationVo;
import com.mida.bms.report.vo.ReportSearchRequest;
import com.mida.bms.report.vo.ReportSearchVo;
import com.mida.bms.ris2.api.request.Ris2RequestAPI;
import com.mida.bms.ris2.dto.request.DocReportListVo;
import com.mida.bms.ris2.dto.request.RequestFormInfo;
import com.mida.dms.mdm.dto.ParameterDto;
import com.mida.dms.mdm.dto.UserDto;
import com.mida.dms.mdm.pojo.auto.MsdParameterValue;
import com.mida.tool.common.result.ListResult;
import com.mida.tool.common.ret.RespBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DocReportListNewServiceImpl extends BaseProcess implements DocReportListNewService {


    @Autowired
    private Ris2RequestAPI ris2RequestAPI;



    @Autowired
    private CacheService cacheService;



    @Autowired
    private DocReportServiceApi docReportServiceApi;


    @Autowired
    private DetailCodingSystemService detailCodingSystemService;



    @Override
    public ListResult risFindPage(PagingQueryVo vo) {
        ListResult result = new ListResult();
        UserDto user = gainUserPart();
        Long hospitalSoid = user.getHospitalSoid();
        //找到报告类型
        ListResult<ParameterDto> parameterByOrgInfoSoid = mdmService.findParameterByOrgInfoSoid(ReportType.REPORT_PARAMETERS_SOID.code, hospitalSoid,
                ReportType.WRITE_REPORT_RESOURCE_INFO_SOID.code);
        Long parameterValueSoid = null;
        if (ObjectUtils.isNotEmpty(parameterByOrgInfoSoid)) {
            ParameterDto parameterDto = parameterByOrgInfoSoid.getData();
            if (ObjectUtils.isNotEmpty(parameterDto)) {
                List<MsdParameterValue> parameterValueList = parameterDto.getParameterValueList();
                if (!CollectionUtils.isEmpty(parameterValueList)) {
                    parameterValueSoid = parameterValueList.get(0).getParameterValueSoid();
                }
            }
        }

        //根据报告的不同类型调用不同的接口
        if (ReportType.WRITE_REPORT_REQUEST.code.equals(parameterValueSoid)) {
            RequestFormInfo requestFormInfo = new RequestFormInfo();
            BeanUtils.copyProperties(vo,requestFormInfo);
            //1、申请单分页查询报告List
            requestFormInfo.setHospitalSoid(hospitalSoid);
            Page<RequestInfoVo> page = this.findPage(requestFormInfo);
            buildListSuccess(result,page);
            return result;
        } else if (ReportType.WRITE_REPORT_EXAMINATIONVISITSOID.code.equals(parameterValueSoid)) {
            //2、以检查号为维度的分页查询报告List
//            ListResult<PageResultVo<DocReportListVo>> pageWithCallingNo = this.findPageWithCallingNo(vo);
//            return pageWithCallingNo;
        } else if (ReportType.WRITE_REPORT_REGISTRATIONNO.code.equals(parameterValueSoid)) {
            //3、以登记号为维度的分页查询报告List
//            ListResult<PageResultVo<DocReportListVo>> pageWithRegisterNo = this.findPageWithRegisterNo(vo);
//            return pageWithRegisterNo;
        }
        buildBadRequestListWarn(result, "没有匹配的报告类型参数");
        return result;
    }






    private Page<RequestInfoVo> findPage(RequestFormInfo requestFormInfo){
        log.info("开始分页查询报告list: " + requestFormInfo.toString());
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult result = new ListResult();
        Page<RequestInfoVo> pvo = new Page();
        UserDto user = gainUserPart();
        if (user == null) {
            pvo.setRecords(null);
            buildListSuccess(result, pvo);
            stopWatch.stop();
            log.info("本次新增耗时:" + stopWatch.getTime() + "ms. user为空");
            return pvo;
        }
        //查询ris2.0
        Page<DocReportListVo> data = ris2RequestAPI.getRequestListInfo(requestFormInfo).getData();
        Page<RequestInfoVo> requestInfoVoPage = new Page<>();
        BeanUtils.copyProperties(data,requestInfoVoPage);
        if(!CollectionUtils.isEmpty(data.getRecords())){
            List<RequestInfoVo> requestInfoVos = BeanUtil.copyToList(data.getRecords(), RequestInfoVo.class);
            requestInfoVoPage.setRecords(requestInfoVos);
            //加上检查类型
//            requestInfoVos.forEach(requestInfoVo->requestInfoVo.setExamType(requestFormInfo.getExamServiceType()));
            //添加检查标识、检查号
            for (RequestInfoVo requestInfoVo : requestInfoVos) {
                if (!CollectionUtils.isEmpty(requestInfoVo.getServiceInstanceVoList())){
                    ServiceInstanceCheckVo instanceCheckVo = requestInfoVo.getServiceInstanceVoList().get(0);
                    requestInfoVo.setExaminationVisitSoid(instanceCheckVo.getExaminationVisitSoid());
                    requestInfoVo.setOperatorSoid(instanceCheckVo.getOperatorSoid());
                }
            }
        }

        List<RequestInfoVo> infoVos = this.gainPortStatusAndDoctor(requestInfoVoPage.getRecords());
        requestInfoVoPage.getRecords().clear();
        requestInfoVoPage.setRecords(infoVos);
        return requestInfoVoPage;
    }




    /**
     * 补充报告状态和书写医生
     *
     * @param list
     */
    private List<RequestInfoVo> gainPortStatusAndDoctor(List<RequestInfoVo> list) {
        log.info("补充报告状态和书写医生begin: " + "==================================================");
        StopWatch stopWatch = StopWatch.createStarted();

        //先读缓存
        List<RequestInfoVo> tmpList = new ArrayList<>();
        List<RequestInfoVo> removList = new ArrayList<>();
        tmpList.addAll(list);
        if (cacheService.enabled()) {
            for (RequestInfoVo dv : list) {
                if (cacheService.exist(dv.getRequestSoid())) {
                    removList.add(dv);
                }
            }
        }
        tmpList.removeAll(removList);


        if(tmpList.size() == 0){//都缓存则不用读数据库
            stopWatch.stop();
            log.info("补充报告状态和书写医生end: " + "==================================================" + "本次耗时:" + stopWatch.getTime() + "ms");
            return list;
        }

        //批量获取 报告状态，审核，书写医生、审核医生
        List<DocReportRequisitionRelationVo> docReportRequisitionRelationVoList = queryDocReportRequisitionRelationVos(tmpList);

        Map<Long, String> employeeMap = new HashMap<>();
        Map<String, DocReportRequisitionRelationVo> relationMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(docReportRequisitionRelationVoList)) {

            //将值集soid为key,值集name为value放入map中
            for (DocReportRequisitionRelationVo vo : docReportRequisitionRelationVoList) {
                //key=申请单标识_登记标识_检查标识
                String key = String.valueOf(vo.getRequestSoid());
//               String key= vo.getRequestSoid()+"_"+vo.getRegistrationFormSoid()+"_"+ vo.getOperatorSoid();
                if (relationMap.get(key) == null) {
                    relationMap.put(key, vo);
                }
            }
            //初始化批量查询员工信息查询条件（人员集合）
            Set<Long> firstWriteDoctors = docReportRequisitionRelationVoList
                    .stream()
                    .map(DocReportRequisitionRelationVo::getFirstWriteDoctor)
                    .collect(Collectors.toSet());
            Set<Long> firstTrialDoctors = docReportRequisitionRelationVoList
                    .stream()
                    .map(DocReportRequisitionRelationVo::getFirstTrialDoctor)
                    .collect(Collectors.toSet());
            firstWriteDoctors.addAll(firstTrialDoctors);
            List<Long> employeeSoids = firstWriteDoctors.stream().distinct().collect(Collectors.toList());
            //批量查询员工信息
            employeeMap = mdmService.findListBySoids(employeeSoids);
        }

        //报告list返回对象中添加报告状态，医生
        list = addParametersToReport(detailCodingSystemService, tmpList, employeeMap, relationMap);
        stopWatch.stop();
        log.info("补充报告状态和书写医生end: " + "==================================================" + "本次耗时:" + stopWatch.getTime() + "ms");
        return list;
    }




    /**
     * @return java.util.List<com.mida.bms.report.vo.DocReportRequisitionRelationVo>
     * @Author WXL
     * @Description 批量获取 报告状态，审核，书写医生、审核医生
     * @Date 2021/8/7
     * @Param [list]
     **/
    private List<DocReportRequisitionRelationVo> queryDocReportRequisitionRelationVos(List<RequestInfoVo> list) {
        List<ReportSearchRequest> reportSearchRequestList = new ArrayList<>();
        list.forEach(docReportListVo -> {
            //包装查询报告状态，审核，书写医生条件
            ReportSearchRequest reportSearchRequest = new ReportSearchRequest();
            reportSearchRequest.setRequestSoid(docReportListVo.getRequestSoid());//申请单标识
            reportSearchRequest.setRegistrationFormSoid(docReportListVo.getRegistrationFormSoid());//登记标识
            reportSearchRequest.setExaminationVisitSoid(docReportListVo.getOperatorSoid()); //检查标识
            reportSearchRequestList.add(reportSearchRequest);
        });
        ReportSearchVo reportSearchVo = new ReportSearchVo(reportSearchRequestList);
        ListResult<List<DocReportRequisitionRelationVo>> listListResult = docReportServiceApi.selectDoctorAndStatusList(reportSearchVo);
        return listListResult.getData();
    }



    /**
     * @return void
     * @Author WXL
     * @Description 报告list返回对象中添加报告状态，医生
     * @Date 2021/8/7
     * @Param [list, employeeMap, relationMap]
     **/
    public List<RequestInfoVo> addParametersToReport(DetailCodingSystemService detailCodingSystemService, List<RequestInfoVo> list, Map<Long, String> employeeMap, Map<String, DocReportRequisitionRelationVo> relationMap) {
        //报告流程状态 map
        Map<Long, String> reportProcessStatusMap = detailCodingSystemService
                .getDataSetMapByDetailCode(DetailCode.REPORT_PROCESS_STATUS_CODE.code, null, false);
        //报告自身状态Map
        Map<Long, String> reportStatusMap = detailCodingSystemService
                .getDataSetMapByDetailCode(DetailCode.REPORT_STATUS.code, null, false);

        Map<Long, String> finalEmployeeMap = employeeMap;
        list.forEach(m -> {
            //补充返回vo中流转状态
            if (m.getRequestSoid() != null) {
                DocReportRequisitionRelationVo docReportRequisitionRelationVo = relationMap.get(String.valueOf(m.getRequestSoid()));
                if (ObjectUtils.isNotEmpty(docReportRequisitionRelationVo)) {
                    //1、报告流程状态
                    Long reportProcessStatus = docReportRequisitionRelationVo.getReportProcessStatus();
                    //报告流程状态
                    if (ObjectUtils.isNotEmpty(reportProcessStatus)) {
                        //设置报告状态soid
                        m.setReportProcessStatus(reportProcessStatus);
                        //报告流转状态名称
                        m.setReportStatus(reportProcessStatusMap.get(reportProcessStatus));
                    }
                    //2、报告自身状态
                    Long status = docReportRequisitionRelationVo.getStatus();
                    if (ObjectUtils.isNotEmpty(status)) {
                        m.setStatus(status);
                        //报告自身状态名称
                        m.setStatusName(reportStatusMap.get(status));
                    }
                    //3、设置报告soid
                    m.setStReportSoid(docReportRequisitionRelationVo.getStReportSoid());
                    //(书写医生)
                    Long firstWriteDoctor = docReportRequisitionRelationVo.getFirstWriteDoctor();
                    //审核医生
                    Long firstTrialDoctor = docReportRequisitionRelationVo.getFirstTrialDoctor();

                    if (ObjectUtils.isNotEmpty(finalEmployeeMap)) {
                        //(书写医生)
                        if (ObjectUtils.isNotEmpty(firstWriteDoctor)) {
                            m.setWritingDoctor(finalEmployeeMap.get(firstWriteDoctor));
                            m.setWritingDoctorSoid(firstWriteDoctor);

                        }
                        //审核医生
                        if (ObjectUtils.isNotEmpty(firstTrialDoctor)) {
                            m.setCheckDoctor(finalEmployeeMap.get(firstTrialDoctor));
                            m.setCheckDoctorSoid(firstTrialDoctor);
                        }

                    }
                } else {
                    //设置报告状态soid
                    m.setReportProcessStatus(ReportProcessStatus.TO_BE_WRITTEN.code);
                    //报告状态名称
                    m.setReportStatus("待书写");
                }
                ReportFlowInfo reportFlowInfo = new ReportFlowInfo();
                BeanUtils.copyProperties(m, reportFlowInfo);
                cacheService.cacheReportFlowInfo(reportFlowInfo);
            }
        });

        return list;
    }
}
